package com.pro.framework.api.util;

import cn.hutool.core.util.ObjUtil;
import com.pro.framework.api.model.IFrameworkException;
import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;

@Slf4j
public class ExceptionUtil {
    public static boolean isRetryableException(Throwable e) {
        return e instanceof java.net.SocketTimeoutException
                || e instanceof java.net.UnknownHostException
                || e instanceof java.nio.channels.UnresolvedAddressException  // 新增这一行
                || e instanceof java.net.ConnectException                     // 也可以考虑加上这个
                || (e.getCause() != null && isRetryableException(e.getCause()));
    }

    public static String logThrowable(Throwable e) {
        return logThrowable(e, null);
    }

    public static String logThrowable(Throwable e, Boolean needMore) {
        return logThrowable(e, needMore, null);
    }

    public static String logThrowable(Throwable e, Boolean needMore, String message) {
        Boolean timeoutSimple = false;
        boolean retryableException = isRetryableException(e);
        if (needMore == null) {
//            e instanceof IFrameworkException ||
            timeoutSimple = retryableException;
            needMore = !(e instanceof IFrameworkException || timeoutSimple);
        }
        StackTraceElement[] stackTrace = e.getStackTrace();
        StringBuilder s = new StringBuilder(retryableException ? "超时异常" : StrUtils.or(message, e.getMessage(), ""));
        if (e instanceof IFrameworkException ef) {
            Object[] params = ef.getParams();
            if (params != null) {
                s.append(Arrays.toString(params));
            }
        }
        s.append("\n");
        if (!timeoutSimple) {
            int i = 0;
            for (StackTraceElement stackTraceElement : stackTrace) {
                String temp = stackTraceElement.toString().trim();
//                 && i < 30
                if ((needMore) || (temp.startsWith("com.pro.") && temp.contains(":"))) {
                    s.append("	").append(temp).append("\n");
                }
                i++;
            }
            if (s.isEmpty()) {
                for (StackTraceElement stackTraceElement : stackTrace) {
                    s.append("	").append(stackTraceElement.toString()).append("\n");
                }
            }
            Throwable cause = e.getCause();
            if (cause != null && e != cause) {
                s.append("	").append(logThrowable(cause, needMore)).append("\n");
            }
        }
        return s.substring(0, s.length() - 1);
    }
}
